package com.example.glgk.utils;

import com.example.glgk.dto.EscalationData;
import com.example.glgk.dto.EscalationDeptData;
import com.example.glgk.dto.QueryEscalation;
import com.example.glgk.dto.gather.ClinicalGatherDataDto;
import com.example.glgk.dto.gather.DataDto;
import com.example.glgk.dto.gather.DeptEscalationDataDto;
import com.example.glgk.dto.gather.HeaderDataDto;
import com.example.glgk.entity.DepartmentIndicatorEntity;
import com.example.glgk.entity.IndicatorDataEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lxk
 * <p>根据公式计算指标值</p>
 */
public class CalculatorUtils {

    // 类的成员变量
    private static ScriptEngine engine;


    // 在类的初始化块或构造方法中进行初始化
    static {
        ScriptEngineManager manager = new ScriptEngineManager();
        engine = manager.getEngineByName("js");
    }

    /**
     * 计算指标值 动态列为月份的计算方法
     *
     * @param elementDays
     * @param calculationFormulaId
     * @return
     */
    public static void calculator(List<DepartmentIndicatorEntity> elementDays, String calculationFormulaId, EscalationData escalationData, QueryEscalation queryEscalation) {
        if (CollectionUtils.isEmpty(elementDays) || StringUtils.isEmpty(calculationFormulaId)) {
            return;
        }
        //计算结果数据
        Map<String, String> map = new LinkedHashMap<>();
        // 使用Map按时间维度分组
        Map<String, List<DepartmentIndicatorEntity>> groupedData = new LinkedHashMap<>();
        for (DepartmentIndicatorEntity entity : elementDays) {
            groupedData.computeIfAbsent(entity.getTime(), k -> new ArrayList<>()).add(entity);
        }

        // 遍历每个时间维度的数据组进行计算
        for (List<DepartmentIndicatorEntity> group : groupedData.values()) {
            // 构建当前组的计算公式
            String formula = calculationFormulaId;
            for (DepartmentIndicatorEntity entity : group) {
                String elementId = "${" + entity.getId() + "}";
                String elementNumber = String.valueOf(entity.getElementNumber());
                formula = formula.replace(elementId, elementNumber);
            }

            // 计算当前组的结果
            try {
                Object result = engine.eval(formula);
                // 检查 result 的类型
                if (result instanceof Double) {
                    // 如果是 Double 类型，转换为 String
                    result = String.valueOf(result);
                }
                if (result instanceof Integer) {
                    // 如果是 Integer 类型，转换为 String
                    result = String.valueOf(result);
                }
                map.put(group.get(0).getTime(), (String) result);
            } catch (ScriptException e) {
                map.put(group.get(0).getTime(), "-");

            }
        }
        escalationData.setDynamicColumns(map);
    }


    /**
     * 动态列非月份 而是多月份汇总的数据
     * @param elementDays
     * @param entity
     * @param calculationFormulaId
     * @param escalationData
     */
    public static void calculator(List<DepartmentIndicatorEntity> elementDays, IndicatorDataEntity entity, String calculationFormulaId, EscalationDeptData escalationData) {
        Map<String, String> map = new LinkedHashMap<>();
        if (CollectionUtils.isEmpty(elementDays) || entity == null) {
            if (escalationData.getDynamicColumns() == null) {
                escalationData.setDynamicColumns(map);
            } else {
                escalationData.getDynamicColumns().put(entity.getIndexName(), "-");
            }
            return;
        }
        //计算结果数据
        // 使用Map按时间维度分组
        Map<String, List<DepartmentIndicatorEntity>> groupedData = new LinkedHashMap<>();
        for (DepartmentIndicatorEntity indicatorEntity : elementDays) {
            groupedData.computeIfAbsent(indicatorEntity.getTime(), k -> new ArrayList<>()).add(indicatorEntity);
        }
        // 遍历每个时间维度的数据组进行计算
        BigDecimal sum = BigDecimal.ZERO;
        //todo 先将每个月份分组计算好了之后，在汇总多月份数据求平均值
        for (List<DepartmentIndicatorEntity> group : groupedData.values()) {
            // 构建当前组的计算公式
            String formula = calculationFormulaId;
            for (DepartmentIndicatorEntity entity1 : group) {
                String elementId = "${" + entity1.getId() + "}";
                String elementNumber = String.valueOf(entity1.getElementNumber());
                formula = formula.replace(elementId, elementNumber);
            }
            // 计算当前组的结果
            try {
                Object result = engine.eval(formula);
                // 检查 result 的类型
                if (result instanceof Double) {
                    result = String.valueOf(result);
                    if(!StringUtils.isEmpty(entity.getIndexUnit())){
                        BigDecimal bigDecimal = new BigDecimal(String.valueOf(result)).setScale(4, BigDecimal.ROUND_HALF_UP);
                        result=String.valueOf(bigDecimal);
                    }
                }
                if (result instanceof Integer) {
                    // 如果是 Integer 类型，转换为 String
                    result = String.valueOf(result);
                }
                sum=sum.add(new BigDecimal(String.valueOf(result)));
            } catch (ScriptException e) {
                if (escalationData.getDynamicColumns() == null) {
                    escalationData.setDynamicColumns(map);
                } else {
                    escalationData.getDynamicColumns().put(entity.getIndexName(), "-");
                }
            }
        }
        BigDecimal divide = sum.divide(new BigDecimal(groupedData.keySet().size()), 4, BigDecimal.ROUND_HALF_UP);
        map.put(entity.getIndexName(), divide.toString());
        escalationData.getDynamicColumns().put(entity.getIndexName(), divide.toString());
    }


    /**
     * 计算指标值 动态列为月份为大表头，指标值，同比，环比为小表头的计算方法
     *
     * @param elementDays
     * @param calculationFormulaId
     * @return
     */
    public static void calculator(List<DepartmentIndicatorEntity> elementDays, String calculationFormulaId, DeptEscalationDataDto escalationData, QueryEscalation queryEscalation) {
        if (CollectionUtils.isEmpty(elementDays) || StringUtils.isEmpty(calculationFormulaId)) {
            return;
        }
        //计算结果数据
        Map<String, HeaderDataDto> map = new LinkedHashMap<>();
        // 使用Map按时间维度分组
        Map<String, List<DepartmentIndicatorEntity>> groupedData = new LinkedHashMap<>();
        for (DepartmentIndicatorEntity entity : elementDays) {
            groupedData.computeIfAbsent(entity.getTime(), k -> new ArrayList<>()).add(entity);
        }

        List<DataDto> list =new ArrayList<>();
        for (String time : groupedData.keySet()) {
            DataDto dataDto =  new DataDto();
            dataDto.setIndicatorName(escalationData.getProject());
            dataDto.setTime(time);
            String formula = calculationFormulaId;
            for (DepartmentIndicatorEntity entity : groupedData.get(time)) {
                String elementId = "${" + entity.getId() + "}";
                String elementNumber = String.valueOf(entity.getElementNumber());
                formula = formula.replace(elementId, elementNumber);
            }
            Object result = null;
            try {
                result = engine.eval(formula);
                // 检查 result 的类型
                if (result instanceof Double) {
                    // 如果是 Double 类型，转换为 String
                    result = String.valueOf(result);
                }
                if (result instanceof Integer) {
                    // 如果是 Integer 类型，转换为 String
                    result = String.valueOf(result);
                }
            } catch (ScriptException e) {
                escalationData.getDynamicColumns().put(time, new HeaderDataDto("-","-","-"));
            }
            if (queryEscalation.getTimes().contains(time)) {
                if(result != null && !"null".equals(String.valueOf(result)) ){
                    //说明当前计算的是指标值
                    dataDto.setIndicator(String.valueOf(result));
                }else{
                    dataDto.setIndicator("-");
                }


            }
            list.add(dataDto);
        }

        //实际要组装的时间
        for (String time : queryEscalation.getTimes()) {
            HeaderDataDto headerDataDto=new HeaderDataDto();
            //推算一下 是否能找到当前时间呢？
            //是否能找到环比时间的值呢？
            String momTime = DateUtils.getMomTime(time);
            String yoyTime =  DateUtils.getYoyTime(time);
            //是否能找到同比时间的值呢？
            for (DataDto dataDto : list) {
                //todo 确保先找到指标值后，再去寻找同比和环比的计算
                if (time.equals(dataDto.getTime())) {
                    headerDataDto.setIndicator(dataDto.getIndicator());
                }
            }

            for (DataDto dataDto : list) {
                try{
                    assert momTime != null;
                    if(momTime.equals(dataDto.getTime())){ //这两个怎么会相等？
                        double momValue =( Double.parseDouble(headerDataDto.getIndicator()) - Double.parseDouble(dataDto.getIndicator()) ) / Double.parseDouble(dataDto.getIndicator());
                        headerDataDto.setMomValue(String.valueOf(momValue));
                    }
                }catch (Exception e){
                    headerDataDto.setMomValue("-");
                    headerDataDto.setYoyValue("-");
                }

                try{
                    assert yoyTime != null;
                    if(yoyTime.equals(dataDto.getTime())){ //这两个怎么会相等？
                        double yoyValue =( Double.parseDouble(headerDataDto.getIndicator()) - Double.parseDouble(dataDto.getIndicator()) ) / Double.parseDouble(dataDto.getIndicator());
                        headerDataDto.setMomValue(String.valueOf(yoyValue));
                    }
                }catch (Exception e){
                    headerDataDto.setYoyValue("-");
                }


            }
                escalationData.getDynamicColumns().put(time, headerDataDto);
            }
        }


    /**
     * 计算指标值 动态列为月份为大表头，指标值，同比，环比为小表头的计算方法
     *
     * @param elementDays
     * @param calculationFormulaId
     * @return
     */
    public static void calculator(List<DepartmentIndicatorEntity> elementDays, String calculationFormulaId, ClinicalGatherDataDto escalationData, QueryEscalation queryEscalation) {
        if (CollectionUtils.isEmpty(elementDays) || StringUtils.isEmpty(calculationFormulaId)) {
            return;
        }
        //计算结果数据
        Map<String, HeaderDataDto> map = new LinkedHashMap<>();
        // 使用Map按时间维度分组
        Map<String, List<DepartmentIndicatorEntity>> groupedData = new LinkedHashMap<>();
        for (DepartmentIndicatorEntity entity : elementDays) {
            groupedData.computeIfAbsent(entity.getTime(), k -> new ArrayList<>()).add(entity);
        }

        List<DataDto> list =new ArrayList<>();
        for (String time : groupedData.keySet()) {
            DataDto dataDto =  new DataDto();
            dataDto.setIndicatorName(escalationData.getIndicatorName());
            dataDto.setTime(time);
            String formula = calculationFormulaId;
            for (DepartmentIndicatorEntity entity : groupedData.get(time)) {
                String elementId = "${" + entity.getId() + "}";
                String elementNumber = String.valueOf(entity.getElementNumber());
                formula = formula.replace(elementId, elementNumber);
            }

            Object result = null;
            try {
                result = engine.eval(formula);
                // 检查 result 的类型
                if (result instanceof Double) {
                    // 如果是 Double 类型，转换为 String
                    result = String.valueOf(result);
                }
                if (result instanceof Integer) {
                    // 如果是 Integer 类型，转换为 String
                    result = String.valueOf(result);
                }
            } catch (ScriptException e) {
                escalationData.getDynamicColumns().put(time, new HeaderDataDto("-","-","-"));
            }
            if (queryEscalation.getTimes().contains(time)) {
                if(result != null && !"null".equals(String.valueOf(result)) ){
                    //说明当前计算的是指标值
                    dataDto.setIndicator(String.valueOf(result));
                }else{
                    dataDto.setIndicator("-");
                }
            }
            list.add(dataDto);
        }

        //实际要组装的时间
        for (String time : queryEscalation.getTimes()) {
            HeaderDataDto headerDataDto=new HeaderDataDto();
            //推算一下 是否能找到当前时间呢？
            //是否能找到环比时间的值呢？
            String momTime = DateUtils.getMomTime(time);
            String yoyTime =  DateUtils.getYoyTime(time);
            //是否能找到同比时间的值呢？
            for (DataDto dataDto : list) {
                //todo 确保先找到指标值后，再去寻找同比和环比的计算
                if (time.equals(dataDto.getTime())) {
                    headerDataDto.setIndicator(dataDto.getIndicator());
                }
            }

            for (DataDto dataDto : list) {
                try{
                    assert momTime != null;
                    if(momTime.equals(dataDto.getTime())){
                        double momValue =( Double.parseDouble(headerDataDto.getIndicator()) - Double.parseDouble(dataDto.getIndicator()) ) / Double.parseDouble(dataDto.getIndicator());
                        headerDataDto.setMomValue(String.valueOf(momValue));
                    }
                }catch (Exception e){
                    headerDataDto.setMomValue("-");
                    headerDataDto.setYoyValue("-");
                }

                try{
                    assert yoyTime != null;
                    if(yoyTime.equals(dataDto.getTime())){
                        double yoyValue =( Double.parseDouble(headerDataDto.getIndicator()) - Double.parseDouble(dataDto.getIndicator()) ) / Double.parseDouble(dataDto.getIndicator());
                        headerDataDto.setMomValue(String.valueOf(yoyValue));
                    }
                }catch (Exception e){
                    headerDataDto.setYoyValue("-");
                }


            }
            escalationData.getDynamicColumns().put(time, headerDataDto);
        }
    }



    }




